﻿
using CSharpLibs.Annotations;

namespace System.Collections
{
	[Builtin]
	public sealed class BitArray : ICollection, IEnumerable, ICloneable
	{
		private bool[] m_array;
		
		private BitArray()
		{ ;}

		public BitArray(int length)
		{
			this.m_array = new bool[length];
		}

		public BitArray(BitArray bits)
		{
			if(bits == null)
				throw new ArgumentNullException("bits");

			this.m_array = (bool[])bits.m_array.Clone();
		}

		public BitArray(bool[] values)
		{
			if(values == null)
				throw new ArgumentNullException("values");

			this.m_array = (bool[])values.Clone();
		}

		public BitArray And(BitArray value)
		{
			if(value == null)
				throw new ArgumentNullException("value");
			
			if(this.m_array.Length != value.m_array.Length)
				throw new ArgumentException("length");
			
			for(int i = 0; i < this.m_array.Length; i++)
				this.m_array[i] &= value.m_array[i];
			
			return this;
		}

		public object Clone()
		{ return new BitArray(this.m_array); }

		public void CopyTo(Array array, int index)
		{
			if(array == null)
				throw new ArgumentNullException("array");

			if(index < 0)
				throw new ArgumentOutOfRangeException("index");

			bool[] flagArray = (bool[])array;
			for(int j = 0; j < this.m_array.Length; j++)
				flagArray[index + j] = this.m_array[j];
		}

		public bool Get(int index)
		{
			if((index < 0) || (index >= this.m_array.Length))
				throw new ArgumentOutOfRangeException("index");
			
			return this.m_array[index];
		}

		public IEnumerator GetEnumerator()
		{ return new BitArrayEnumeratorSimple(this); }

		public BitArray Not()
		{
			for(int i = 0; i < this.m_array.Length; i++)
				this.m_array[i] = !this.m_array[i];
			
			return this;
		}

		public BitArray Or(BitArray value)
		{
			if(value == null)
				throw new ArgumentNullException("value");
			
			if(this.m_array.Length != value.m_array.Length)
				throw new ArgumentException("length");
			
			for(int i = 0; i < this.m_array.Length; i++)
				this.m_array[i] |= value.m_array[i];
			
			return this;
		}

		public void Set(int index, bool value)
		{
			if((index < 0) || (index >= this.m_array.Length))
				throw new ArgumentOutOfRangeException("index");
			
			this.m_array[index] = value;
		}

		public void SetAll(bool value)
		{
			for(int i = 0; i < this.m_array.Length; i++)
				this.m_array[i] = value;
		}

		public BitArray Xor(BitArray value)
		{
			if(value == null)
				throw new ArgumentNullException("value");
			
			if(this.m_array.Length != value.m_array.Length)
				throw new ArgumentException("length");
			
			for(int i = 0; i < this.m_array.Length; i++)
				this.m_array[i] ^= value.m_array[i];
		
			return this;
		}

		// Properties
		public int Count
		{ get { return this.m_array.Length; } }

		public bool this[int index]
		{
			get { return this.Get(index); }

			set { this.Set(index, value); }
		}

		public int Length
		{
			get { return this.m_array.Length; }
		}

		private class BitArrayEnumeratorSimple : IEnumerator, ICloneable
		{
			private BitArray bitarray;
			private bool currentElement;
			private int index;
			
			internal BitArrayEnumeratorSimple(BitArray bitarray)
			{
				this.bitarray = bitarray;
				this.index = -1;
			}

			public object Clone()
			{ return base.MemberwiseClone(); }

			public bool MoveNext()
			{
				if(this.index < (this.bitarray.Count - 1))
				{
					this.index++;
					this.currentElement = this.bitarray.Get(this.index);
					return true;
				}
				this.index = this.bitarray.Count;
				return false;
			}

			public void Reset()
			{ this.index = -1; }

			public object Current
			{
				get	{ return this.currentElement; }
			}
		}
	}
}
